package com.shuwen.gcdj.service.file;



import com.shuwen.gcdj.common.util.IOCloseUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Component
@Slf4j
@AllArgsConstructor
public class FilePackaging {


    public static final int  BUFFER_SIZE = 1024 * 1024;

    @Value("${savepath}")
    private static String FileName;

    /**
     * 压缩成ZIP 方法1
     * @param file 压缩文件对象
     * @param outputStream    压缩文件输出流
     * @param KeepDirStructure  是否保留原来的目录结构,true:保留目录结构;
     * 							false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
//    public static void mainpp() throws FileNotFoundException {
//        byte[] buffer = new byte[BUFFER_SIZE];
//
//        FileOutputStream outputStream = new FileOutputStream("D:\\xiaoyip\\xiaoyi.zip");
//        ZipOutputStream  zipOutputStream = new ZipOutputStream(outputStream, Charset.forName("UTF-8"));
//
//        File file = new File("D:\\xiaoyip\\xiaoyi.mp4");
//        FileInputStream fis = new FileInputStream(file);
//        ZipEntry zipEntry = new ZipEntry(file.getName());
//        zipOutputStream.putNextEntry(zipEntry);
//
//        int length;
//        while ((length = fis.read(buffer)) >= 0) {
//            zipOutputStream.write(buffer, 0, length);
//        }
//
//        zipOutputStream.closeEntry();
//        fis.close();
//    }

    public static void toZip(String sourceFileName,HttpServletResponse response)
            throws RuntimeException {
        ZipOutputStream out = null;
        BufferedOutputStream bos = null;
        try {
            //将zip以流的形式输出到前台
            response.setHeader("content-type", "application/zip");
            response.setCharacterEncoding("utf-8");
            // 设置浏览器响应头对应的Content-disposition
            //参数中 testZip 为压缩包文件名，尾部的.zip 为文件后缀
            response.setHeader("Content-disposition",
                    "attachment;filename=" + new String("ocn".getBytes("gbk"), "iso8859-1")+".zip");
            //创建zip输出流
            out = new ZipOutputStream(response.getOutputStream());
            //创建缓冲输出流
            bos = new BufferedOutputStream(out);
            File sourceFile = new File(sourceFileName);
            //调用压缩函数
            compress(out, bos, sourceFile, sourceFile.getName());
            out.flush();

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            IOCloseUtil.close(bos, out);
        }
    }

    /**
     * 文件压缩
     * @param out
     * @param bos
     * @param sourceFile
     * @param base
     */
    public static void compress(ZipOutputStream out, BufferedOutputStream bos, File sourceFile, String base){
        FileInputStream fos = null;
        BufferedInputStream bis = null;
        try {
            //如果路径为目录（文件夹）
            if (sourceFile.isDirectory()) {
                //取出文件夹中的文件（或子文件夹）
                File[] flist = sourceFile.listFiles();
                if (flist.length == 0) {//如果文件夹为空，则只需在目的地zip文件中写入一个目录进入点
                    out.putNextEntry(new ZipEntry(base + "/"));
                } else {//如果文件夹不为空，则递归调用compress，文件夹中的每一个文件（或文件夹）进行压缩
                    for (int i = 0; i < flist.length; i++) {
                        compress(out, bos, flist[i], base + "/" + flist[i].getName());
                    }
                }
            } else {//如果不是目录（文件夹），即为文件，则先写入目录进入点，之后将文件写入zip文件中
                out.putNextEntry(new ZipEntry(base));
                fos = new FileInputStream(sourceFile);
                bis = new BufferedInputStream(fos);

                int tag;
                //将源文件写入到zip文件中
                while ((tag = bis.read()) != -1) {
                    out.write(tag);
                }
                bis.close();
                fos.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            IOCloseUtil.close(bis,fos);
        }
    }


    /**
     * 下载文件
     * @param response
     * @param fileUrl
     */
    public static void download(HttpServletResponse response,String fileUrl) {
        try {
            File file=new File(fileUrl);
            String filename=file.getName();
            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(fileUrl));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            response.setContentType("application/octet-stream;charset=UTF-8");
            String fileName = new String(filename.getBytes("gb2312"), "iso8859-1");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName);
            OutputStream ouputStream = response.getOutputStream();
            ouputStream.write(buffer);
            ouputStream.flush();
            ouputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文件下载出现异常", e);
        }
    }


    public static void copyFiles(String src, String tag,Boolean flag) {
        try {
            File srcFolder = new File(src);
            //原始文件名
            String srcFloderName = srcFolder.getName();
            //要复制到的文件
            File desFolder = new File(tag, srcFloderName);
            //如果要复制到的文件没有这个文件夹，就创建一个
            if ((!desFolder.exists()) && flag){
                desFolder.mkdir();
            }
            copyFolder(srcFolder,desFolder);
            srcFolder.delete();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static  void copyFolder(File srcFolder, File desFolder) throws IOException {

        //遍历原始文件夹里面的所有文件及文件夹
        File[] files = srcFolder.listFiles();
        if(files!=null && srcFolder.isDirectory() ){
            for (File srcFile : files) {
                //如果是文件夹
                if (srcFile.isDirectory()){
                    //在新的文件夹内创建一个和srcFile文件夹同名文件夹，然后再递归调用，判断文件夹里面的情况，然后做出相应处理
                    String srcFileName = srcFile.getName();
                    File newFolder = new File(desFolder, srcFileName);
                    if (!newFolder.exists()){
                        newFolder.mkdir();
                        copyFolder(srcFile,newFolder);
                    }
                    //如果是文件
                }else {
                    String srcFileName = srcFile.getName();
                    File desFile = new File(desFolder, srcFileName);
                    copyFile(srcFile,desFile);
                }

            }
        } else if (files==null && srcFolder.isDirectory()){
            desFolder.mkdirs();
            return;
        }else {
            File desFile = new File(desFolder.toString());
            copyFile(srcFolder,desFile);
        }

    }

    /**
     * 复制文件
     * @param srcFile
     * @param desFile
     */
    private  static void copyFile (File srcFile, File desFile)  {
        FileInputStream fileInputStream = null;
        FileOutputStream outputStream=null;
        BufferedInputStream bufferedInputStream=null;
        BufferedOutputStream bufferedOutputStream=null;

        try {
            fileInputStream = new FileInputStream(srcFile);
             outputStream = new FileOutputStream(desFile);
             bufferedInputStream = new BufferedInputStream(fileInputStream);
             bufferedOutputStream = new BufferedOutputStream(outputStream);
            int len;
            while ((len = bufferedInputStream.read()) != -1) {
                bufferedOutputStream.write(len);
                bufferedOutputStream.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
                try {
                    bufferedInputStream.close();
                    bufferedOutputStream.close();
                    fileInputStream.close();
                    outputStream.close();
                    srcFile.delete();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }



    }




}
